<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  
  
  
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <title>
    java8函数式编程 |
    
    M_W_Q</title>
  
    <link rel="shortcut icon" href="/bolg/favicon.ico">
  
  <link rel="stylesheet" href="/bolg/css/style.css">
  
    <link rel="stylesheet" href="/bolg/fancybox/jquery.fancybox.min.css">
  
  <script src="/bolg/js/pace.min.js"></script>
</head>

<body>
<main class="content">
  <section class="outer">
  

<article id="post-java8函数式编程" class="article article-type-post" itemscope itemprop="blogPost" data-scroll-reveal>
  
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      java8函数式编程
    </h1>
  
  




      </header>
    

    
      <div class="article-meta">
        <a href="/bolg/2019/10/23/java8%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B/" class="article-date">
  <time datetime="2019-10-23T13:04:49.273Z" itemprop="datePublished">2019-10-23</time>
</a>
        
      </div>
    

    
      
    <div class="tocbot"></div>





    

    <div class="article-entry" itemprop="articleBody">
      


      

      
        <h3 id="Java-8-函数式编程"><a href="#Java-8-函数式编程" class="headerlink" title="Java 8 函数式编程"></a>Java 8 函数式编程</h3><p>java8函数式核心概念</p>
<ul>
<li>函数接口（Funtion）</li>
<li>流（stream）</li>
<li>聚合器（Collector）</li>
</ul>
<h4 id="函数接口"><a href="#函数接口" class="headerlink" title="函数接口"></a>函数接口</h4><ul>
<li>函数接口是行为的抽象</li>
<li>函数接口是数据转换器<h5 id="四大基础函数接口"><a href="#四大基础函数接口" class="headerlink" title="四大基础函数接口"></a>四大基础函数接口</h5></li>
<li>Supplier ：数据提供器，没有输入参数， 输出为类型T</li>
<li>Function：数据转换器，接收一个 T 类型的对象，返回一个 R类型的对象，提供apply，compose，andThen，identity</li>
<li>Consumer：数据消费器，  接收一个 T类型的对象，无返回值，通常用于根据T对象做些处理，提供accept，andThen</li>
<li>Predicate：条件测试器，条件测试器，接收一个 T 类型的对象，返回布尔值，通常用于传递条件函数，提供了 test (条件测试) , and-or- negate(与或非) 方法<h5 id="扩展函数接口"><a href="#扩展函数接口" class="headerlink" title="扩展函数接口"></a>扩展函数接口</h5></li>
<li>参数扩展：接受双参数Bi前缀</li>
<li>类型扩展：接受原子类型参数</li>
<li>特殊变形：BinaryOperator</li>
</ul>
<h5 id="函数接口接入参数"><a href="#函数接口接入参数" class="headerlink" title="函数接口接入参数"></a>函数接口接入参数</h5><ul>
<li>类/对象的静态方法引用，实例方法引用(PS: 使用::)</li>
<li>类的构造器（PS: Class::new）</li>
<li>lambda表达式</li>
</ul>
<h4 id="聚合器"><a href="#聚合器" class="headerlink" title="聚合器"></a>聚合器</h4><p>流的最后都是使用Collect来进行数据聚合，返回数据</p>
<h5 id="Reduce"><a href="#Reduce" class="headerlink" title="Reduce"></a>Reduce</h5><p>Reduce推导需要的是三个重要的参数</p>
<ul>
<li>init初始数据</li>
<li>二元操作符BinaryOperator</li>
<li>聚合结果源s<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> num1 = list.stream().reduce(<span class="number">0</span>, (a, b) -&gt; a + b);</span><br></pre></td></tr></table></figure>
<h5 id="聚合器四要素"><a href="#聚合器四要素" class="headerlink" title="聚合器四要素"></a>聚合器四要素</h5></li>
<li>容器的初始化（Supplier）</li>
<li>一个用于将每次二元操作的中间结果与结果容器的值进行操作并重新设置结果容器的累积器 accumulator</li>
<li>一个用于对Stream元素和中间结果进行操作的二元操作符 combiner</li>
<li>一个用于对结果容器进行最终聚合的转换器 finisher(非必须)<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line">     * Simple implementation class for &#123;@code Collector&#125;.</span><br><span class="line">     *</span><br><span class="line">     * @param &lt;T&gt; the type of elements to be collected</span><br><span class="line">     * @param &lt;R&gt; the type of the result</span><br><span class="line">     */</span><br><span class="line">static class CollectorImpl&lt;T, A, R&gt; implements Collector&lt;T, A, R&gt; &#123;</span><br><span class="line">        private final Supplier&lt;A&gt; supplier;</span><br><span class="line">        private final BiConsumer&lt;A, T&gt; accumulator;</span><br><span class="line">        private final BinaryOperator&lt;A&gt; combiner;</span><br><span class="line">        private final Function&lt;A, R&gt; finisher;</span><br><span class="line">        private final Set&lt;Characteristics&gt; characteristics;</span><br><span class="line">        CollectorImpl(Supplier&lt;A&gt; supplier,</span><br><span class="line">                      BiConsumer&lt;A, T&gt; accumulator,</span><br><span class="line">                      BinaryOperator&lt;A&gt; combiner,</span><br><span class="line">                      Function&lt;A,R&gt; finisher,</span><br><span class="line">                      Set&lt;Characteristics&gt; characteristics) &#123;</span><br><span class="line">            this.supplier = supplier;</span><br><span class="line">            this.accumulator = accumulator;</span><br><span class="line">            this.combiner = combiner;</span><br><span class="line">            this.finisher = finisher;</span><br><span class="line">            this.characteristics = characteristics;</span><br><span class="line">        &#125;</span><br><span class="line">        CollectorImpl(Supplier&lt;A&gt; supplier,</span><br><span class="line">                      BiConsumer&lt;A, T&gt; accumulator,</span><br><span class="line">                      BinaryOperator&lt;A&gt; combiner,</span><br><span class="line">                      Set&lt;Characteristics&gt; characteristics) &#123;</span><br><span class="line">            this(supplier, accumulator, combiner, castingIdentity(), characteristics);</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
toList()执行操作<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * Returns a &#123;@code Collector&#125; that accumulates the input elements into a</span><br><span class="line"> * new &#123;@code List&#125;. There are no guarantees on the type, mutability,</span><br><span class="line"> * serializability, or thread-safety of the &#123;@code List&#125; returned; if more</span><br><span class="line"> * control over the returned &#123;@code List&#125; is required, use &#123;@link #toCollection(Supplier)&#125;.</span><br><span class="line"> *</span><br><span class="line"> * @param &lt;T&gt; the type of the input elements</span><br><span class="line"> * @return a &#123;@code Collector&#125; which collects all the input elements into a</span><br><span class="line"> * &#123;@code List&#125;, in encounter order</span><br><span class="line"> */</span><br><span class="line">public static &lt;T&gt;</span><br><span class="line">Collector&lt;T, ?, List&lt;T&gt;&gt; toList() &#123;</span><br><span class="line">    return new CollectorImpl&lt;&gt;((Supplier&lt;List&lt;T&gt;&gt;) ArrayList::new, List::add,</span><br><span class="line">                               (left, right) -&gt; &#123; left.addAll(right); return left; &#125;,</span><br><span class="line">                               CH_ID);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li>第一个参数是初始化数据通过ArrayList::new创建</li>
<li>第二个参数是执行的操作，list的add元素添加操作</li>
<li>第三个参数是执行最后的聚合操作</li>
</ul>
<h5 id="映射类聚合器"><a href="#映射类聚合器" class="headerlink" title="映射类聚合器"></a>映射类聚合器</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">private static &lt;K, V, M extends Map&lt;K,V&gt;&gt;</span><br><span class="line">    BinaryOperator&lt;M&gt; mapMerger(BinaryOperator&lt;V&gt; mergeFunction) &#123;</span><br><span class="line">        return (m1, m2) -&gt; &#123;</span><br><span class="line">            for (Map.Entry&lt;K,V&gt; e : m2.entrySet())</span><br><span class="line">                m1.merge(e.getKey(), e.getValue(), mergeFunction);</span><br><span class="line">            return m1;</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>根据指定的值合并函数 mergeFunction, 返回一个map合并器，用来合并两个map里相同key的值。mergeFunction用来对两个map中相同key的值进行运算得到新的value值，如果value值为null，会移除相应的key，否则使用value值作为对应key的值。这个方法是私有的，主要为支撑 toMap，groupingBy 而生。</p>
<h5 id="自定义聚合器"><a href="#自定义聚合器" class="headerlink" title="自定义聚合器"></a>自定义聚合器</h5><p>需要实现Collector，构造四要素：</p>
<ul>
<li>可变的结果容器Supplier:初始化的参数，注意不能初始化不可变的：supplier</li>
<li>累积器 BiConsumer:使用参数来进行和终止，新元素放入结果容器中：accumulator()</li>
<li>组合器 BInaryOperator ：目前无作用：combiner()</li>
<li>最终转换器 Funcation: 最终返回数据模型：finisher() <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line">public class CollectorsImpls implements Collector&lt;Integer, List&lt;Integer&gt;, List&lt;Integer&gt;&gt; &#123;</span><br><span class="line">    /**</span><br><span class="line">     * A function that creates and returns a new mutable result container.</span><br><span class="line">     *</span><br><span class="line">     * @return a function which returns a new, mutable result container</span><br><span class="line">     */</span><br><span class="line">    @Override</span><br><span class="line">    public Supplier&lt;List&lt;Integer&gt;&gt; supplier() &#123;</span><br><span class="line">        return () -&gt; &#123;</span><br><span class="line">            List&lt;Integer&gt; res = new ArrayList&lt;&gt;();</span><br><span class="line">            res.add(0);</span><br><span class="line">            res.add(1);</span><br><span class="line">            return res;</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * A function that folds a value into a mutable result container.</span><br><span class="line">     *</span><br><span class="line">     * @return a function which folds a value into a mutable result container</span><br><span class="line">     */</span><br><span class="line">    @Override</span><br><span class="line">    public BiConsumer&lt;List&lt;Integer&gt;, Integer&gt; accumulator() &#123;</span><br><span class="line">        return (res, num) -&gt; &#123;</span><br><span class="line">            Integer next = res.get(res.size() - 1) + res.get(res.size() - 2);</span><br><span class="line">            res.add(next);</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * A function that accepts two partial results and merges them.  The</span><br><span class="line">     * combiner function may fold state from one argument into the other and</span><br><span class="line">     * return that, or may return a new result container.</span><br><span class="line">     *</span><br><span class="line">     * @return a function which combines two partial results into a combined</span><br><span class="line">     * result</span><br><span class="line">     */</span><br><span class="line">    @Override</span><br><span class="line">    public BinaryOperator&lt;List&lt;Integer&gt;&gt; combiner() &#123;</span><br><span class="line"></span><br><span class="line">        return (res1, res2) -&gt; &#123;</span><br><span class="line">            Integer num = res1.get(res1.size()) + res2.get(res2.size());</span><br><span class="line">            res1.add(num);</span><br><span class="line">            return res1;</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * Perform the final transformation from the intermediate accumulation type</span><br><span class="line">     * &#123;@code A&#125; to the final result type &#123;@code R&#125;.</span><br><span class="line">     *</span><br><span class="line">     * &lt;p&gt;If the characteristic &#123;@code IDENTITY_TRANSFORM&#125; is</span><br><span class="line">     * set, this function may be presumed to be an identity transform with an</span><br><span class="line">     * unchecked cast from &#123;@code A&#125; to &#123;@code R&#125;.</span><br><span class="line">     *</span><br><span class="line">     * @return a function which transforms the intermediate result to the final</span><br><span class="line">     * result</span><br><span class="line">     */</span><br><span class="line">    @Override</span><br><span class="line">    public Function&lt;List&lt;Integer&gt;, List&lt;Integer&gt;&gt; finisher() &#123;</span><br><span class="line">        return res -&gt; &#123;</span><br><span class="line">            res.remove(0);</span><br><span class="line">            res.remove(1);</span><br><span class="line">            return res;</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * Returns a &#123;@code Set&#125; of &#123;@code Collector.Characteristics&#125; indicating</span><br><span class="line">     * the characteristics of this Collector.  This set should be immutable.</span><br><span class="line">     *</span><br><span class="line">     * @return an immutable set of collector characteristics</span><br><span class="line">     */</span><br><span class="line">    @Override</span><br><span class="line">    public Set&lt;Characteristics&gt; characteristics() &#123;</span><br><span class="line">        return Collections.emptySet();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List&lt;Integer&gt; fibo = Arrays.asList(1,1,1,1).stream().collect(new CollectorsImpls());</span><br></pre></td></tr></table></figure>
<h4 id="流"><a href="#流" class="headerlink" title="流"></a>流</h4><h5 id="Stream流接口"><a href="#Stream流接口" class="headerlink" title="Stream流接口"></a>Stream流接口</h5>Stream 主要四类接口</li>
<li>流与流之间的转换：<ul>
<li>filter(过滤)</li>
<li>map(映射转换),</li>
<li>mapToInt|Long|Double, flatMap(高维结构平铺)</li>
<li>flatMapTo[Int|Long|Double] </li>
<li>sorted(排序)</li>
<li>distinct(不重复值)</li>
<li>peek(执行某种操作，流不变，可用于调试)</li>
<li>limit(限制到指定元素数量)</li>
<li>skip(跳过若干元素</li>
</ul>
</li>
<li>流与值的转化<ul>
<li>toArray（转为数组）</li>
<li>reduce（推导结果）</li>
<li>collect（聚合结果）</li>
<li>min(最小值)</li>
<li>max(最大值)</li>
<li>count (元素个数)</li>
<li>anyMatch (任一匹配)</li>
<li>allMatch(所有都匹配)</li>
<li>noneMatch(一个都不匹配)</li>
<li>findFirst（选择首元素）</li>
<li>findAny(任选一元素)</li>
</ul>
</li>
<li>遍历<ul>
<li>forEach(不保序遍历，比如并行流)</li>
<li>forEachOrdered（保序遍历)</li>
</ul>
</li>
<li>构造流<ul>
<li>empty (构造空流)</li>
<li>of (单个元素的流及多元素顺序流)</li>
<li>iterate (无限长度的有序顺序流)</li>
<li>generate (将数据提供器转换成无限非有序的顺序流)</li>
<li>concat (流的连接)</li>
<li>Builder (用于构造流的Builder对象)<h5 id="流的主要类型"><a href="#流的主要类型" class="headerlink" title="流的主要类型"></a>流的主要类型</h5></li>
</ul>
</li>
<li>Reference（对象流）</li>
<li>IntStream（int元素流）</li>
<li>LongStream（long元素流）</li>
<li>DoubleStream （double元素流）<h5 id="collector实现"><a href="#collector实现" class="headerlink" title="collector实现"></a>collector实现</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">public final &lt;R, A&gt; R collect(Collector&lt;? super P_OUT, A, R&gt; collector) &#123;</span><br><span class="line">        A container;</span><br><span class="line">        if (isParallel()</span><br><span class="line">                &amp;&amp; (collector.characteristics().contains(Collector.Characteristics.CONCURRENT))</span><br><span class="line">                &amp;&amp; (!isOrdered() || collector.characteristics().contains(Collector.Characteristics.UNORDERED))) &#123;</span><br><span class="line">            container = collector.supplier().get();</span><br><span class="line">            BiConsumer&lt;A, ? super P_OUT&gt; accumulator = collector.accumulator();</span><br><span class="line">            forEach(u -&gt; accumulator.accept(container, u));</span><br><span class="line">        &#125;</span><br><span class="line">        else &#123;</span><br><span class="line">            container = evaluate(ReduceOps.makeRef(collector));</span><br><span class="line">        &#125;</span><br><span class="line">        return collector.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)</span><br><span class="line">               ? (R) container</span><br><span class="line">               : collector.finisher().apply(container);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
主要的重要的操作<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">public static &lt;T, I&gt; TerminalOp&lt;T, I&gt;</span><br><span class="line">    makeRef(Collector&lt;? super T, I, ?&gt; collector) &#123;</span><br><span class="line">        Supplier&lt;I&gt; supplier = Objects.requireNonNull(collector).supplier();</span><br><span class="line">        BiConsumer&lt;I, ? super T&gt; accumulator = collector.accumulator();</span><br><span class="line">        BinaryOperator&lt;I&gt; combiner = collector.combiner();</span><br><span class="line">        class ReducingSink extends Box&lt;I&gt;</span><br><span class="line">                implements AccumulatingSink&lt;T, I, ReducingSink&gt; &#123;</span><br><span class="line">            @Override</span><br><span class="line">            public void begin(long size) &#123;</span><br><span class="line">                state = supplier.get();</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            @Override</span><br><span class="line">            public void accept(T t) &#123;</span><br><span class="line">                accumulator.accept(state, t);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            @Override</span><br><span class="line">            public void combine(ReducingSink other) &#123;</span><br><span class="line">                state = combiner.apply(state, other.state);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        return new ReduceOp&lt;T, I, ReducingSink&gt;(StreamShape.REFERENCE) &#123;</span><br><span class="line">            @Override</span><br><span class="line">            public ReducingSink makeSink() &#123;</span><br><span class="line">                return new ReducingSink();</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            @Override</span><br><span class="line">            public int getOpFlags() &#123;</span><br><span class="line">                return collector.characteristics().contains(Collector.Characteristics.UNORDERED)</span><br><span class="line">                       ? StreamOpFlag.NOT_ORDERED</span><br><span class="line">                       : 0;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">final &lt;R&gt; R evaluate(TerminalOp&lt;E_OUT, R&gt; terminalOp) &#123;</span><br><span class="line">       assert getOutputShape() == terminalOp.inputShape();</span><br><span class="line">       if (linkedOrConsumed)</span><br><span class="line">           throw new IllegalStateException(MSG_STREAM_LINKED);</span><br><span class="line">       linkedOrConsumed = true;</span><br><span class="line"></span><br><span class="line">       return isParallel()</span><br><span class="line">              ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags()))</span><br><span class="line">              : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags()));</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>
Box 是一个结果值的持有者； ReducingSink 用begin, accept, combine 三个方法定义了要进行的计算；ReducingSink是有状态的流数据消费的计算抽象，阅读Sink接口文档可知。ReduceOps.makeRef(collector) 返回了一个封装了Reduce操作的ReduceOps对象。注意到，这里都是声明要执行的计算，而不涉及计算的实际过程。展示了表达与执行分离的思想。真正的计算过程启动在 ReferencePipeline.evaluate 方法里</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * Evaluate the pipeline with a terminal operation to produce a result.</span><br><span class="line"> *</span><br><span class="line"> * @param &lt;R&gt; the type of result</span><br><span class="line"> * @param terminalOp the terminal operation to be applied to the pipeline.</span><br><span class="line"> * @return the result</span><br><span class="line"> */</span><br><span class="line">final &lt;R&gt; R evaluate(TerminalOp&lt;E_OUT, R&gt; terminalOp) &#123;</span><br><span class="line">    assert getOutputShape() == terminalOp.inputShape();</span><br><span class="line">    if (linkedOrConsumed)</span><br><span class="line">        throw new IllegalStateException(MSG_STREAM_LINKED);</span><br><span class="line">    linkedOrConsumed = true;</span><br><span class="line"></span><br><span class="line">    return isParallel()</span><br><span class="line">           ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags()))</span><br><span class="line">           : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags()));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">@Override</span><br><span class="line">    final &lt;P_IN&gt; void copyInto(Sink&lt;P_IN&gt; wrappedSink, Spliterator&lt;P_IN&gt; spliterator) &#123;</span><br><span class="line">        Objects.requireNonNull(wrappedSink);</span><br><span class="line"></span><br><span class="line">        if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) &#123;</span><br><span class="line">            wrappedSink.begin(spliterator.getExactSizeIfKnown());</span><br><span class="line">            spliterator.forEachRemaining(wrappedSink);</span><br><span class="line">            wrappedSink.end();</span><br><span class="line">        &#125;</span><br><span class="line">        else &#123;</span><br><span class="line">            copyIntoWithCancel(wrappedSink, spliterator);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>Spliterator 用来对流中的元素进行分区和遍历以及施加Sink指定操作，可以用于并发计算。Spliterator的具体实现类定义在 Spliterators 的静态类和静态方法中。其中有：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">数组Spliterator:</span><br><span class="line">static final class ArraySpliterator&lt;T&gt; implements Spliterator&lt;T&gt;</span><br><span class="line">static final class IntArraySpliterator implements Spliterator.OfInt</span><br><span class="line">static final class LongArraySpliterator implements Spliterator.OfLong</span><br><span class="line">static final class DoubleArraySpliterator implements Spliterator.OfDouble</span><br><span class="line"></span><br><span class="line">迭代Spliterator:</span><br><span class="line">static class IteratorSpliterator&lt;T&gt; implements Spliterator&lt;T&gt;</span><br><span class="line">static final class IntIteratorSpliterator implements Spliterator.OfInt</span><br><span class="line">static final class LongIteratorSpliterator implements Spliterator.OfLong</span><br><span class="line">static final class DoubleIteratorSpliterator implements Spliterator.OfDouble</span><br><span class="line"></span><br><span class="line">抽象Spliterator:</span><br><span class="line">public static abstract class AbstractSpliterator&lt;T&gt; implements Spliterator&lt;T&gt;</span><br><span class="line">private static abstract class EmptySpliterator&lt;T, S extends Spliterator&lt;T&gt;, C&gt;</span><br><span class="line">public static abstract class AbstractIntSpliterator implements Spliterator.OfInt</span><br><span class="line">public static abstract class AbstractLongSpliterator implements Spliterator.OfLong</span><br><span class="line">public static abstract class AbstractDoubleSpliterator implements Spliterator.OfDouble</span><br></pre></td></tr></table></figure>
<p>每个具体的类都是实现了trySplit, forEachRemaining,tryAdvance,estimateSize,characteriscs,getComparator.</p>
<ul>
<li>trypSplit：用于流拆分，提供并发能力</li>
<li>forEachRemaining：遍历流中的数据</li>
<li>tryAdvance：消费流数据<br>整体的流程：</li>
<li>Collector定义必要的聚合操作函数</li>
<li>ReduceOps.makeRef 将 Collector 封装成一个计算对象 ReduceOps ，依赖的 ReducingSink 定义了具体的流数据消费过程</li>
<li>Spliterator 用于对流中的元素进行分区和遍历以及施加Sink指定的操作<h5 id="Pipeline"><a href="#Pipeline" class="headerlink" title="Pipeline"></a>Pipeline</h5>类 java.util.stream.AbstractPipeline 的方法 sourceSpliterator 拿到并且这里的 sourceStage 是一个 AbstractPipeline。 Pipeline 是实现流式计算的流水线抽象，也是Stream的实现类。可以看到，java.util.stream 定义了四种 pipeline: DoublePipeline, IntPipeline, LongPipeline, ReferencePipeline。<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">@Override</span><br><span class="line">    public final Stream&lt;P_OUT&gt; filter(Predicate&lt;? super P_OUT&gt; predicate) &#123;</span><br><span class="line">        Objects.requireNonNull(predicate);</span><br><span class="line">        return new StatelessOp&lt;P_OUT, P_OUT&gt;(this, StreamShape.REFERENCE,</span><br><span class="line">                                     StreamOpFlag.NOT_SIZED) &#123;</span><br><span class="line">            @Override</span><br><span class="line">            Sink&lt;P_OUT&gt; opWrapSink(int flags, Sink&lt;P_OUT&gt; sink) &#123;</span><br><span class="line">                return new Sink.ChainedReference&lt;P_OUT, P_OUT&gt;(sink) &#123;</span><br><span class="line">                    @Override</span><br><span class="line">                    public void begin(long size) &#123;</span><br><span class="line">                        downstream.begin(-1);</span><br><span class="line">                    &#125;</span><br><span class="line"></span><br><span class="line">                    @Override</span><br><span class="line">                    public void accept(P_OUT u) &#123;</span><br><span class="line">                        if (predicate.test(u))</span><br><span class="line">                            downstream.accept(u);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
套路基本一样，关键点在于 accept 方法。filter 只在满足条件时将值传给下一个 pipeline, 而 map 将计算的值传给下一个 pipeline. StatelessOp 没有什么逻辑，JDK文档解释是：Base class for a stateless intermediate stage of a Stream。相应还有一个 StatefulOp, Head。 这些都是 ReferencePipeline ，负责将值在 pipeline 之间传递，交给 Sink 去计算<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">static class Head&lt;E_IN, E_OUT&gt; extends ReferencePipeline&lt;E_IN, E_OUT&gt;</span><br><span class="line">abstract static class StatelessOp&lt;E_IN, E_OUT&gt; extends ReferencePipeline&lt;E_IN, E_OUT&gt;</span><br><span class="line">abstract static class StatefulOp&lt;E_IN, E_OUT&gt; extends ReferencePipeline&lt;E_IN, E_OUT&gt;</span><br></pre></td></tr></table></figure></li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://m_aleen.gitee.io/bolg/2019/10/23/java8%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B/" data-id="ck32z8yug000a69db7lwc6mgi"
         class="article-share-link">Share</a>
      
    </footer>

  </div>

  
    
  <nav class="article-nav">
    
    
      <a href="/bolg/2019/10/23/%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3/" class="article-nav-link">
        <strong class="article-nav-caption">Olde posts</strong>
        <div class="article-nav-title">自定义注解（hibernate-validator实现）</div>
      </a>
    
  </nav>


  

  
    
  

</article>



</section>
  <footer class="footer">
  <div class="outer">
    <div class="float-right">
      <ul class="list-inline">
  
    <li><i class="fe fe-smile-alt"></i> <span id="busuanzi_value_site_uv"></span></li>
  
    <li><i class="fe fe-bookmark"></i> <span id="busuanzi_value_page_pv"></span></li>
  
</ul>
    </div>
    <ul class="list-inline">
      <li>&copy; 2019 M_W_Q</li>
      <li>Powered by <a href="http://hexo.io/" target="_blank">Hexo</a></li>
      <li>Theme  <a href="https://github.com/zhwangart/hexo-theme-ocean" target="_blank" rel="noopener">Ocean</a></li>
    </ul>
  </div>
</footer>

</main>

<aside class="sidebar sidebar-specter">
  
    <button class="navbar-toggle"></button>
<nav class="navbar">
  
    <div class="logo">
      <a href="/bolg/"><img src="/bolg/images/hexo.svg" alt="M_W_Q"></a>
    </div>
  
  <ul class="nav nav-main">
    
      <li class="nav-item">
        <a class="nav-item-link" href="/bolg/">Home</a>
      </li>
    
      <li class="nav-item">
        <a class="nav-item-link" href="/bolg/archives">Archives</a>
      </li>
    
      <li class="nav-item">
        <a class="nav-item-link" href="/bolg/gallery">Gallery</a>
      </li>
    
      <li class="nav-item">
        <a class="nav-item-link" href="/bolg/about">About</a>
      </li>
    
    <li class="nav-item">
      <a class="nav-item-link nav-item-search" title="搜索">
        <i class="fe fe-search"></i>
        Search
      </a>
    </li>
  </ul>
</nav>
<nav class="navbar navbar-bottom">
  <ul class="nav">
    <li class="nav-item">
      <div class="totop" id="totop">
  <i class="fe fe-rocket"></i>
</div>
    </li>
    <li class="nav-item">
      
        <a class="nav-item-link" target="_blank" href="/bolg/atom.xml" title="RSS Feed">
          <i class="fe fe-feed"></i>
        </a>
      
    </li>
  </ul>
</nav>
<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
  </aside>
  <script src="/bolg/js/jquery-2.0.3.min.js"></script>
<script src="/bolg/js/jquery.justifiedGallery.min.js"></script>
<script src="/bolg/js/lazyload.min.js"></script>
<script src="/bolg/js/busuanzi-2.3.pure.min.js"></script>

  <script src="/bolg/fancybox/jquery.fancybox.min.js"></script>



  <script src="/bolg/js/tocbot.min.js"></script>
  <script>
    // Tocbot_v4.7.0  http://tscanlin.github.io/tocbot/
    tocbot.init({
      tocSelector: '.tocbot',
      contentSelector: '.article-entry',
      headingSelector: 'h1, h2, h3, h4, h5, h6',
      hasInnerContainers: true,
      scrollSmooth: true,
      positionFixedSelector: '.tocbot',
      positionFixedClass: 'is-position-fixed',
      fixedSidebarOffset: 'auto',
    });
  </script>


<script src="/bolg/js/ocean.js"></script>

</body>
</html>